from typing import Any, Optional, TypeVar, Generic
from pydantic import BaseModel, Field
from fastapi.encoders import jsonable_encoder
from fastapi.responses import JSONResponse
from fastapi import status

T = TypeVar('T')

class ResponseModel(BaseModel, Generic[T]):
    """统一响应模型"""
    code: int = Field(default=200, description="状态码")
    message: str = Field(default="success", description="响应信息")
    data: Optional[T] = Field(default=None, description="响应数据")

    class Config:
        json_encoders = {
            # 可以在这里添加自定义的编码器
        }

def success_response(
    *,
    data: Any = None,
    message: str = "success",
    code: int = 200
) -> JSONResponse:
    """成功响应
    
    Args:
        data: 响应数据
        message: 响应信息
        code: 状态码
        
    Returns:
        JSONResponse: JSON响应对象
    """
    return JSONResponse(
        status_code=status.HTTP_200_OK,
        content=jsonable_encoder(
            ResponseModel(
                code=code,
                message=message,
                data=data
            )
        )
    )

def error_response(
    *,
    message: str = "error",
    code: int = 400,
    data: Any = None
) -> JSONResponse:
    """错误响应
    
    Args:
        message: 错误信息
        code: 错误码
        data: 错误数据
        
    Returns:
        JSONResponse: JSON响应对象
    """
    return JSONResponse(
        status_code=code,
        content=jsonable_encoder(
            ResponseModel(
                code=code,
                message=message,
                data=data
            )
        )
    )

def list_response(
    *,
    items: list,
    total: int,
    page: int = 1,
    size: int = 10,
    message: str = "success",
    code: int = 200
) -> JSONResponse:
    """列表响应
    
    Args:
        items: 列表数据
        total: 总数
        page: 当前页码
        size: 每页大小
        message: 响应信息
        code: 状态码
        
    Returns:
        JSONResponse: JSON响应对象
    """
    return JSONResponse(
        status_code=status.HTTP_200_OK,
        content=jsonable_encoder(
            ResponseModel(
                code=code,
                message=message,
                data={
                    "items": items,
                    "total": total,
                    "page": page,
                    "size": size
                }
            )
        )
    )
